import jwt
import datetime
from datetime import datetime, timedelta
from flask import request, jsonify
from flask_jwt_extended import create_access_token, get_jwt_identity, jwt_required, get_jwt
from api.apps.utils.log import logger
from api.apps.users import users_bp
from api.apps.users.models import User
from api.apps.users.schema import UserSchema
from api.apps.utils.responses import response_with
from api.apps.utils import responses as resp
from api.config import Config

secret_key = Config.JWT_SECRET_KEY


def get_json_data():
  """提取并验证 JSON 数据。"""
  data = request.get_json()
  if not data:
    raise ValueError("No JSON data provided")
  return data


# 生成 Token
def generate_token(user_id):
  # 获取当前 UTC 时间
  utc_now = datetime.datetime.now(datetime.timezone.utc)
  expiration = utc_now + timedelta(hours=1)
  payload = {
    'user_id': user_id,
    'exp': expiration
  }
  return jwt.encode(payload, secret_key, algorithm='HS256')


# 生成刷新 Token
def generate_refresh_token(user_id):
  # 获取当前 UTC 时间
  utc_now = datetime.datetime.now(datetime.timezone.utc)
  expiration = utc_now + timedelta(days=7)
  payload = {
    'user_id': user_id,
    'exp': expiration
  }
  return jwt.encode(payload, secret_key, algorithm='HS256')


# 注册
@users_bp.route('/register', methods=['POST'])
def create_user():
  """
      用户注册接口
      ---
      parameters:
          - in: body
            name: body
            schema:
              required:
                  - username
                  - password
              properties:
                  username:
                      type: string
                      description: 用户名
                      default: ""
                  password:
                      type: string
                      description: 用户密码
                      default: ""
      responses:
          201:
              description: 注册成功
              schema:
                  properties:
                      code:
                          type: string
          422:
              description: 注册失败
              schema:
                  properties:
                      code:
                          type: string
                      message:
                          type: string
  """
  try:
    data = get_json_data()
    if User.find_by_username(data['username']):
      return response_with(resp.INVALID_INPUT_422, value={"message": "Username already exists"})
    data['password'] = User.generate_hash(data['password'])
    user_schema = UserSchema()
    user = user_schema.load(data)
    result = user_schema.dump(user.create())
    return response_with(resp.SUCCESS_201, value={"user": result})
  except ValueError as e:
    logger.error(f"ValueError: {e}")
    return response_with(resp.INVALID_INPUT_422)


@users_bp.route('/check_username', methods=['GET'])
def check_username():
  username = request.args.get('username')
  if User.find_by_username(username):
    return response_with(resp.SUCCESS_200, value={"exists": True})
  return response_with(resp.SUCCESS_200, value={"exists": False})


# 登录
@users_bp.route('/login', methods=['POST'])
def authenticate_user():
  try:
    data = get_json_data()
    current_user = User.find_by_username(data['username'])
    if not current_user:
      return response_with(resp.SERVER_ERROR_404, value={"message": "User not found"})
    if not User.verify_hash(data['password'], current_user.password):
      return response_with(resp.UNAUTHORIZED_401, value={"message": "Invalid password"})
    # 设置过期时间为 1 小时
    expires = timedelta(hours=1)
    # 使用用户 ID 作为 identity
    access_token = create_access_token(identity=str(current_user.id), expires_delta=expires)
    return response_with(resp.SUCCESS_200, value={
      "message": f"Logged in as {current_user.username}",
      "access_token": access_token
    })
  except ValueError as e:
    logger.error(f"ValueError: {e}")
    return response_with(resp.INVALID_INPUT_422)


# 刷新 Token 接口
@users_bp.route('/refresh_token', methods=['POST'])
def refresh_token():
  token = request.json.get('refresh_token')
  try:
    decoded = jwt.decode(token, secret_key, algorithms=['HS256'])
    user_id = decoded.get('user_id')
    new_token = generate_token(user_id)
    return jsonify({
      'token': new_token
    })
  except jwt.ExpiredSignatureError:
    return jsonify({'message': 'Refresh token expired'}), 401
  except jwt.InvalidTokenError:
    return jsonify({'message': 'Invalid refresh token'}), 401


# 定义 /info 接口
@users_bp.route('/info', methods=['GET'])
@jwt_required()
def get_user_info():
  # 获取当前用户的身份
  try:
    user_id = int(get_jwt_identity())
    current_user = User.find_by_id(user_id)
    if not current_user:
      return response_with(resp.SERVER_ERROR_404, value={"message": "User not found"})
    user_schema = UserSchema()
    user_info = user_schema.dump(current_user)
    return response_with(resp.SUCCESS_200, value={"user": user_info})
    # avatar图标，从后端获取
    # return response_with(resp.SUCCESS_200, value={"user": user_info,
    #                                               "avatar": "https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif"})
  except Exception as e:
    logger.error(f"Error in /info: {e}")
    return response_with(resp.SERVER_ERROR_500, value={"message": "Internal server error"})


# 初始化黑名单集合
jwt_blacklist = set()


# 定义 /logout 接口
@users_bp.route('/logout', methods=['POST'])
@jwt_required()
def logout_user():
  try:
    jti = get_jwt()['jti']  # 获取当前 token 的唯一标识
    jwt_blacklist.add(jti)  # 将 token 加入黑名单
    return response_with(resp.SUCCESS_200, value={"message": "Logged out successfully"})
  except Exception as e:
    logger.error(f"Error during logout: {e}")
    return response_with(resp.SERVER_ERROR_500, value={"message": "Logout failed"})
